﻿using SuperX.Common;
using SuperX.Common.BasicService;
using SuperX.Common.Collection;
using SuperX.Common.Log;
using SuperX.DataService.Abstract;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;

namespace SuperX.DataService
{
    public abstract class DriverBase : BasicObjCollection<IBasicObject>, IDriver
    {
        protected bool _closed = true;
        protected short _id;
        protected string _ip;
        protected int _port = 102;
        protected int _timeout = 1000;
        protected IDataServer _server;

        public string ConfigName { get; set; }

        public DriverBase()
        {
        }

        public DriverBase(IDataServer parent, string name, string nodeKey)
        {
            _server = parent;
            _DriverGroup = new ObjectCollection<DriverBase, IGroup>(this);
            Name = name;
            NodeKey = nodeKey;
            Parent = parent;
        }

        public virtual bool Closed
        {
            set
            {
                if (_closed != value)
                {
                    _closed = value;
                    OnClosedChanged(EventArgs.Empty);
                }
            }
        }

        protected virtual void OnClosedChanged(EventArgs e)
        {
            ClosedChanged?.Invoke(this, e);
        }

        public override IBasicObject this[string name]
        {
            get
            {
                var group = DriverGroup[name];
                if (group == null)
                    return DriverGroup[name];
                return group;
            }
        }

        protected static Dictionary<string, string> AddressConstDict = new Dictionary<string, string>();

        protected ObjectCollection<DriverBase, IGroup> _DriverGroup;

        public ObjectCollection<DriverBase, IGroup> DriverGroup
        {
            get => _DriverGroup ?? (_DriverGroup = new ObjectCollection<DriverBase, IGroup>(this));
            set
            {
                _DriverGroup = value;
                _DriverGroup.SetParent(this);
            }
        }

        /// <summary>
        ///
        /// </summary>
        public virtual int TimeOut
        {
            get
            {
                return _timeout;
            }
            set
            {
                _timeout = value;
            }
        }

        /// <summary>
        /// 驱动父类，DataManager
        /// </summary>
        [JsonIgnore]
        public IDataServer DriverParent
        {
            get { return _server; }
        }

        public virtual IEnumerable<IGroup> Groups
        {
            get { return DriverGroup.Values; }
        }

        /// <summary>
        /// 驱动ID
        /// </summary>
        public short ID
        {
            get
            {
                return _id;
            }
        }

        /// <summary>
        /// 关闭标记
        /// </summary>
        public virtual bool IsClosed
        {
            get
            {
                return _closed;
            }
        }

        /// <summary>
        /// 分块值
        /// </summary>
        public virtual int PDU { get => 220; }

        /// <summary>
        /// 端口
        /// </summary>
        public virtual int Port
        {
            get { return _port; }
            set { _port = value; }
        }

        /// <summary>
        /// 服务名称/设备IP
        /// </summary>
        public virtual string ServerName
        {
            get
            {
                return _ip;
            }
            set
            {
                _ip = value;
            }
        }

        private string _driverNO;

        /// <summary>
        /// 设备编号，资产编码
        /// </summary>
        public string DriverNO
        {
            get
            {
                if (string.IsNullOrEmpty(_driverNO))
                    _driverNO = Guid.NewGuid().ToString();
                return _driverNO;
            }
            set { _driverNO = value; }
        }

        private bool _enabled;

        /// <summary>
        /// 是否启用
        /// </summary>
        public bool Enabled
        {
            get { return _enabled; }
            set { _enabled = value; }
        }

        private DateTime _expiryTime;

        /// <summary>
        /// 是否启用
        /// </summary>
        public DateTime ExpiryTime
        {
            get { return _expiryTime; }
            set { _expiryTime = value; }
        }

        public string Key { get => FullName; }

        public string NodeKey
        {
            get => _nodeKey;
            set
            {
                _nodeKey = value;
            }
        }

        private string _nodeKey = "Server";

        public event IOErrorEventHandler OnError;

        public event ClosedChangedEventHandler ClosedChanged;

        public override string FullName
        {
            get
            {
                if (Parent != null && Parent.FullName != null && !string.IsNullOrEmpty(NodeKey))
                {
                    return $"{Parent.FullName}.{NodeKey}.{Name}";
                }
                return base.FullName;
            }
        }

        public override List<string> GetKeys()
        {
            return DriverGroup.Keys.ToList();
        }

        public override List<IBasicObject> GetValues()
        {
            var group = DriverGroup.Values.OfType<IBasicObject>().ToList();
            return group;
        }

        public override bool IsUniqueName(string name, IObjCollection parent)
        {
            if (parent != null)
            {
                return parent.IsUniqueName(name, null);
            }

            return DriverGroup[name] == null;
        }

        public virtual ItemData<dynamic> ReadDynamic(DeviceAddress address)
        {
            throw new NotImplementedException();
        }

        public virtual bool Connect()
        {
            Logger.Info($"{Name}连接成功！");
            return true;
        }

        public virtual GroupConfig GetSystemGroup()
        {
            var group = new GroupConfig { Name = TagConfig.Defalut, IsActive = true, UpdateRate = 3000, GroupType = TagType.System, Description = "系统分组" };
            group.TagGroups.Add(new TagConfig { Name = TagConfig.WorkState, DataType = DataType.INT, Maximum = 999, Description = "运行状态", TagType = TagType.System });
            group.TagGroups.Add(new TagConfig { Name = TagConfig.Online, DataType = DataType.INT, Maximum = 999, Description = "物联状态", TagType = TagType.System });
            group.TagGroups.Add(new TagConfig { Name = TagConfig.AlarmState, DataType = DataType.INT, Maximum = 999, Description = "报警状态", TagType = TagType.System });
            return group;
        }

        public virtual void GetDefaultConfig(DriverConfig config)
        {
        }

        public abstract bool CheckAddressLegal(string address, DataType dataType);

        public abstract Dictionary<string, string> GetRegester();

        public virtual string AddressCombin(string Register, string No)
        {
            return Register + No;
        }

        public abstract IGroup AddGroup(string name, int updateRate, float deadBand = 0, bool active = false);

        public virtual bool RemoveGroup(IGroup group)
        {
            group.IsActive = false;
            return DriverGroup.Remove(group);
        }

        public virtual List<TreeModel> GetTrees()
        {
            return null;
        }

        public virtual List<GridItem> GetGrids(string parentName)
        {
            return null;
        }

        public override void Dispose()
        {
            Logger.Info($"断开设备{this.FullName}");
            base.Dispose();
        }

        protected virtual DeviceAddress GetDefaultDeviceAddr(TagConfig meta)
        {
            DeviceAddress dv = DeviceAddress.Empty;
            dv.Addr = meta.Address;
            dv.VarType = meta.DataType;
            return dv;
        }
    }
}